using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MusicManager : MonoBehaviour
{
    [Header("Music Settings")]
    [SerializeField] private List<AudioClip> musicPlaylist = new List<AudioClip>();
    [SerializeField] private bool shufflePlaylist = true;
    [SerializeField] private bool loopPlaylist = true;
    [SerializeField] private float trackDuration = 60f;

    [Header("Volume Settings")]
    [SerializeField] private float musicVolume = .5f;

    private AudioSource audioSource;
    private int currentTrackIndex = -1;
    private List<int> shuffledIndices;
    private Coroutine trackCoroutine;

    public static MusicManager Instance { get; private set; }

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
            SetupAudioSource();
        }
        else
        {
            Destroy(gameObject);
            return;
        }
    }

    private void Start()
    {
        if (musicPlaylist.Count > 0)
        {
            if (shufflePlaylist)
            {
                ShufflePlaylist();
            }

            PlayNextTrack();
        }
    }

    private void SetupAudioSource()
    {
        audioSource = GetComponent<AudioSource>();

        if (audioSource == null)
        {
            audioSource = gameObject.AddComponent<AudioSource>();
        }

        audioSource.playOnAwake = false;
        audioSource.loop = true;
        audioSource.volume = musicVolume;
    }

    private void ShufflePlaylist()
    {
        shuffledIndices = new List<int>();

        for (int i = 0; i < musicPlaylist.Count; i++)
        {
            shuffledIndices.Add(i);
        }

        for (int i = shuffledIndices.Count - 1; i > 0; i--)
        {
            int randomIndex = Random.Range(0, i + 1);
            int temp = shuffledIndices[i];
            shuffledIndices[i] = shuffledIndices[randomIndex];
            shuffledIndices[randomIndex] = temp;
        }
    }

    public void PlayNextTrack()
    {
        if (musicPlaylist.Count == 0)
            return;

        currentTrackIndex++;

        if (currentTrackIndex >= musicPlaylist.Count)
        {
            if (loopPlaylist)
            {
                currentTrackIndex = 0;

                if (shufflePlaylist)
                {
                    ShufflePlaylist();
                }
            }
            else
            {
                return;
            }
        }

        int trackIndex = GetCurrentTrackIndex();
        PlayTrack(trackIndex);
    }

    private int GetCurrentTrackIndex()
    {
        if (shufflePlaylist && shuffledIndices != null && shuffledIndices.Count > 0)
        {
            return shuffledIndices[currentTrackIndex];
        }

        return currentTrackIndex;
    }

    private void PlayTrack(int index)
    {
        if (index < 0 || index >= musicPlaylist.Count)
            return;

        AudioClip track = musicPlaylist[index];

        if (track == null)
        {
            PlayNextTrack();
            return;
        }

        if (trackCoroutine != null)
        {
            StopCoroutine(trackCoroutine);
        }

        audioSource.clip = track;
        audioSource.loop = true;
        audioSource.Play();

        trackCoroutine = StartCoroutine(TrackDurationTimer());
    }

    private IEnumerator TrackDurationTimer()
    {
        yield return new WaitForSecondsRealtime(trackDuration);

        audioSource.Stop();
        PlayNextTrack();

        trackCoroutine = null;
    }

    #region Public Methods
    public void PlayMusic()
    {
        if (audioSource != null && !audioSource.isPlaying)
        {
            audioSource.Play();
        }
    }

    public void PauseMusic()
    {
        if (audioSource != null && audioSource.isPlaying)
        {
            audioSource.Pause();
        }
    }

    public void StopMusic()
    {
        if (audioSource != null)
        {
            audioSource.Stop();
        }

        if (trackCoroutine != null)
        {
            StopCoroutine(trackCoroutine);
            trackCoroutine = null;
        }
    }

    public void SetVolume(float volume)
    {
        musicVolume = Mathf.Clamp01(volume);

        if (audioSource != null)
        {
            audioSource.volume = musicVolume;
        }
    }

    public float GetVolume()
    {
        return musicVolume;
    }

    public void SkipToNextTrack()
    {
        StopMusic();
        PlayNextTrack();
    }

    public string GetCurrentTrackName()
    {
        if (audioSource != null && audioSource.clip != null)
        {
            return audioSource.clip.name;
        }

        return "Nenhuma música";
    }
    #endregion
}